/*
 *  CEResetedSliderModule.cpp
 *  LID Library
 *
 *  Created by Alexander Trutchenko on 09/11/11.
 *  Copyright 2011 League of Independent Developers. All rights reserved.
 *
 */

#include "cocos2dx_extentions/controls/CEResetedSliderModule.h"

#include "cocos2dx_extentions/utility/CECocos2dUtility.h"

using namespace cocos2d;

namespace cocosext {

#define CE_SLIDER_MODULE_X_SHIFT 5.f
#define CE_SLIDER_MODULE_Y_SHIFT 5.f

#define CE_SLIDER_MODULE_BTN_FONT			"Marker Felt"
#define CE_SLIDER_MODULE_BTN_COLOR			ccc3(255, 255, 0)
#define CE_SLIDER_MODULE_BTN_R_SIZE			20
#define CE_SLIDER_MODULE_BTN_PLUS_SIZE		24
#define CE_SLIDER_MODULE_BTN_MINUS_SIZE		30

#define CE_SLIDER_MODULE_LABEL_FONT				"Arial"
#define CE_SLIDER_MODULE_LABEL_NAME_SIZE		20
#define CE_SLIDER_MODULE_LABEL_DIGITS_SIZE		18

/////////////////////////////////////////////////////
//
/** CEResetedSliderModule 
* 
*/
/////////////////////////////////////////////////////

/* Static constructor */
CEResetedSliderModule* CEResetedSliderModule::node( cocos2d::CCSprite* backNormal, 
													cocos2d::CCSprite* backDisabled, 
													cocos2d::CCSprite* btnNormal, 
													cocos2d::CCSprite* btnDisabled, 
													float sliderMargin,
													const char* sliderKey,
													float anyInitValue)
{
	CEResetedSliderModule *pRet = new CEResetedSliderModule(sliderKey);
	CCAssert(pRet != NULL, NULL);
	if (pRet->init(backNormal, 
				   backDisabled, 
				   btnNormal, 
				   btnDisabled, 
				   sliderMargin, 
				   anyInitValue))
	{
		pRet->autorelease();
        return pRet;
	}
	else
	{
		CC_SAFE_DELETE(pRet)
		return NULL;
	}
}

bool CEResetedSliderModule::init(cocos2d::CCSprite* backNormal, 
								cocos2d::CCSprite* backDisabled, 
								cocos2d::CCSprite* btnNormal, 
								cocos2d::CCSprite* btnDisabled, 
								float sliderMargin, 
								float anyInitValue)
{
    //self init
//    if (!CCNode::init() )
//        return false;

	std::string key = _sliderKey + CE_SLIDE_MODULE_MIN_VALUE;
	_minValue = CCUserDefault::sharedUserDefault()->getFloatForKey(key.c_str(), _minValue);
	key = _sliderKey + CE_SLIDE_MODULE_MAX_VALUE;
	_maxValue = CCUserDefault::sharedUserDefault()->getFloatForKey(key.c_str(), _maxValue);
	key = _sliderKey + CE_SLIDE_MODULE_VALUE;
	float value = CCUserDefault::sharedUserDefault()->getFloatForKey(key.c_str(), anyInitValue);
	key = _sliderKey + CE_SLIDE_MODULE_RESET_VALUE;
	_resetValue = CCUserDefault::sharedUserDefault()->getFloatForKey(key.c_str(), _resetValue);

	if (value < _minValue || value > _maxValue)
	{
		float delta = _maxValue - _minValue; 
		_minValue = value - delta*_resetValue*0.5f;
		_maxValue = value + delta*_resetValue*0.5f;
	}

	//Labels
	
	_lbName = CCLabelTTF::labelWithString(_sliderKey.c_str(), CE_SLIDER_MODULE_LABEL_FONT, CE_SLIDER_MODULE_LABEL_NAME_SIZE);
	this->addChild(_lbName);

	char tmp[50]; memset(tmp, 0, 50);

	sprintf(tmp, "%.2f", _minValue);
	_lbMinValue = CCLabelTTF::labelWithString(tmp, CE_SLIDER_MODULE_LABEL_FONT, CE_SLIDER_MODULE_LABEL_DIGITS_SIZE);
	this->addChild(_lbMinValue);

	sprintf(tmp, "%.2f", _maxValue);
	_lbMaxValue = CCLabelTTF::labelWithString(tmp, CE_SLIDER_MODULE_LABEL_FONT, CE_SLIDER_MODULE_LABEL_DIGITS_SIZE);
	this->addChild(_lbMaxValue);

	sprintf(tmp, "%.2f", value);
	_lbValue = CCLabelTTF::labelWithString(tmp, CE_SLIDER_MODULE_LABEL_FONT, CE_SLIDER_MODULE_LABEL_DIGITS_SIZE);
	this->addChild(_lbValue);

	sprintf(tmp, "%.2f", _resetValue);
	_lbResetValue = CCLabelTTF::labelWithString(tmp, CE_SLIDER_MODULE_LABEL_FONT, CE_SLIDER_MODULE_LABEL_DIGITS_SIZE);
	this->addChild(_lbResetValue);


	//Menu
	_menu = CCMenu::node();
    _menu->setAnchorPoint(CCPointZero);
    _menu->setPosition(CCPointZero);
    this->addChild(_menu, 0);
   
    CCMenuItemFont::setFontName(CE_SLIDER_MODULE_BTN_FONT);

	CCMenuItemFont::setFontSize(CE_SLIDER_MODULE_BTN_R_SIZE);
    CCMenuItemFont* menuItemPlus = CCMenuItemFont::itemFromString("+", this, menu_selector(CEResetedSliderModule::onIncreaseResetValue));
    menuItemPlus->setColor(CE_SLIDER_MODULE_BTN_COLOR);
	_menu->addChild(menuItemPlus, 0);

	CCMenuItemFont::setFontSize(CE_SLIDER_MODULE_BTN_PLUS_SIZE);
    CCMenuItemFont* menuItemMinus = CCMenuItemFont::itemFromString("-", this, menu_selector(CEResetedSliderModule::onDecreaseResetValue));
    menuItemMinus->setColor(CE_SLIDER_MODULE_BTN_COLOR);
	_menu->addChild(menuItemMinus, 0);

	CCMenuItemFont::setFontSize(CE_SLIDER_MODULE_BTN_R_SIZE);
	CCMenuItemFont* menuItemR = CCMenuItemFont::itemFromString("R", this, menu_selector(CEResetedSliderModule::onReset));
	menuItemR->setColor(CE_SLIDER_MODULE_BTN_COLOR);
	_menu->addChild(menuItemR, 0);

    _slider = CEHorizontalSlider::node(backNormal, 
                                            backDisabled, 
                                            btnNormal, 
                                            btnDisabled, 
                                            sliderMargin, 
                                            (value - _minValue)/(_maxValue - _minValue));
    _slider->setIsEnabled(true);
	_slider->registerDelegate(this, false);
	_slider->setIsRelativeAnchorPoint(true);
    this->addChild(_slider);
    
	CCSize contentSize(0.f, 0.f);
	contentSize.width = _slider->getContentSize().width;
	contentSize.width += _lbResetValue->getContentSize().height;
	contentSize.width += menuItemR->getContentSize().width;
	contentSize.width += CE_SLIDER_MODULE_X_SHIFT*2.f;
	contentSize.height = _slider->getContentSize().height + _lbName->getContentSize().height + _lbValue->getContentSize().height + CE_SLIDER_MODULE_Y_SHIFT*2.f;

	this->setContentSize(contentSize);
	_menu->setContentSize(contentSize);

	menuItemR->setAnchorPoint(ccp(0.f, 0.5f));
	menuItemR->setPosition(ccp(0.f, contentSize.height/2.f));

	_slider->setAnchorPoint(ccp(0.5f, 0.5f));
	_slider->setPosition(ccp(menuItemR->getContentSize().width + CE_SLIDER_MODULE_X_SHIFT + _slider->getContentSize().width/2.f, contentSize.height/2.f));

	_lbName->setAnchorPoint(ccp(0.5f, 1.0f));
	_lbName->setPosition(ccp(contentSize.width/2.f, contentSize.height));

	_lbMinValue->setAnchorPoint(ccp(0.f, 0.f));
	_lbMinValue->setPosition(ccp(_slider->getPosition().x - _slider->getContentSize().width/2.f, 0));

	_lbValue->setAnchorPoint(ccp(0.5f, 0.f));
	_lbValue->setPosition(ccp(_slider->getPosition().x, 0));

	_lbMaxValue->setAnchorPoint(ccp(1.f, 0.f));
	_lbMaxValue->setPosition(ccp(_slider->getPosition().x + _slider->getContentSize().width/2.f, 0));
	
	_lbResetValue->setAnchorPoint(ccp(0.f, 0.5f));
	_lbResetValue->setPosition(ccp(_slider->getPosition().x + _slider->getContentSize().width/2.f + CE_SLIDER_MODULE_X_SHIFT, contentSize.height/2.f));

	menuItemPlus->setAnchorPoint(ccp(0.5f, 1.f));
	menuItemPlus->setPosition(ccp(contentSize.width, contentSize.height));

	menuItemMinus->setAnchorPoint(ccp(0.5f, 0.f));
	menuItemMinus->setPosition(ccp(contentSize.width, 0));

    return true;
}



/////////////////////////////////////////////////////
// public interface

/* Get/set slider value */
float CEResetedSliderModule::getValue() const
{
	return (_minValue + _slider->getValue()*(_maxValue - _minValue));
};

void CEResetedSliderModule::setValue(float value)
{
	_slider->setValue((value - _minValue)/(_maxValue - _minValue));
}

/* Enable/disable slider */
void CEResetedSliderModule::setIsEnabled(bool enabled)
{
	_menu->setIsTouchEnabled(enabled);
	_slider->setIsEnabled(enabled);
}

bool CEResetedSliderModule::isEnabled() const 
{ 
	return _slider->isEnabled(); 
}

/* Register/unregister delegates */
void CEResetedSliderModule::registerDelegate(CESliderDelegate* delegate, bool synchronize)
{
	_realDelegates.push_back(delegate);
	if (synchronize)
		delegate->onValueChange(this);
}

void CEResetedSliderModule::unregisterDelegate(CESliderDelegate* delegate)
{
	_realDelegates.remove(delegate);
}

/////////////////////////////////////////////////////
// protected interface
    /* Callbacks from slider */
void CEResetedSliderModule::onValueChange(CESliderInterface* slider)
{
    for (CESliderDelegates::const_iterator it = _realDelegates.begin(); it != _realDelegates.end(); ++it)
        (*it)->onValueChange(this);
	char tmp[50]; memset(tmp, 0, 50);
	sprintf(tmp, "%.2f", getValue());
	_lbValue->setString(tmp);
}

void CEResetedSliderModule::onSlideBegin(CESliderInterface* slider)
{
    for (CESliderDelegates::const_iterator it = _realDelegates.begin(); it != _realDelegates.end(); ++it)
        (*it)->onSlideBegin(this);
}

void CEResetedSliderModule::onSlideEnd(CESliderInterface* slider)
{
    for (CESliderDelegates::const_iterator it = _realDelegates.begin(); it != _realDelegates.end(); ++it)
        (*it)->onSlideEnd(this);

	std::string key = _sliderKey + CE_SLIDE_MODULE_VALUE;
	CCUserDefault::sharedUserDefault()->setFloatForKey(key.c_str(), getValue());
	CCUserDefault::sharedUserDefault()->flush();
}

void CEResetedSliderModule::onSlideCancelled(CESliderInterface* slider)
{
    for (CESliderDelegates::const_iterator it = _realDelegates.begin(); it != _realDelegates.end(); ++it)
        (*it)->onSlideCancelled(this);
}


/////////////////////////////////////////////////////
// private interface
void CEResetedSliderModule::onIncreaseResetValue(CCObject* caller)
{
	_resetValue *= 2.f;
	char tmp[50]; memset(tmp, 0, 50);
	sprintf(tmp, "%.2f", _resetValue);
	_lbResetValue->setString(tmp);
}

void CEResetedSliderModule::onDecreaseResetValue(CCObject* caller)
{
	_resetValue /= 2.f;
	char tmp[50]; memset(tmp, 0, 50);
	sprintf(tmp, "%.2f", _resetValue);
	_lbResetValue->setString(tmp);
}

void CEResetedSliderModule::onReset(CCObject* caller)
{
	char tmp[50]; memset(tmp, 0, 50);
	float value = getValue();

	float delta = _maxValue - _minValue; 

	_minValue = value - delta*_resetValue*0.5f;
	sprintf(tmp, "%.2f", _minValue);
	_lbMinValue->setString(tmp);

	std::string key = _sliderKey + CE_SLIDE_MODULE_MIN_VALUE;
	CCUserDefault::sharedUserDefault()->setFloatForKey(key.c_str(), _minValue);

	_maxValue = value + delta*_resetValue*0.5f;
	sprintf(tmp, "%.2f", _maxValue);
	_lbMaxValue->setString(tmp);

	key = _sliderKey + CE_SLIDE_MODULE_MAX_VALUE;
	CCUserDefault::sharedUserDefault()->setFloatForKey(key.c_str(), _maxValue);

	CCUserDefault::sharedUserDefault()->flush();

	_slider->setValue(0.5f);
}

}; // end namespace cocosext

